// SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
// SPDX-License-Identifier: GPL-3.0-only

package storage

import (
	"sync"
)

type ChangeAndCallId struct {
	ChangeId string
	CallId   string
}

type _ChangeNoticeDao struct {
	watchToRecvIdMap map[string][]string
	recvChanMap      map[string]chan *ChangeAndCallId
	lock             sync.Mutex
}

func newChangeNoticeDao() *_ChangeNoticeDao {
	return &_ChangeNoticeDao{
		watchToRecvIdMap: make(map[string][]string),
		recvChanMap:      make(map[string]chan *ChangeAndCallId),
	}
}

func (db *_ChangeNoticeDao) AddRecv(watchId, recvId string, recvChan chan *ChangeAndCallId) {
	db.lock.Lock()
	defer db.lock.Unlock()

	recvIdList, ok := db.watchToRecvIdMap[watchId]
	if !ok {
		recvIdList = []string{}
	}
	recvIdList = append(recvIdList, recvId)
	db.watchToRecvIdMap[watchId] = recvIdList

	db.recvChanMap[recvId] = recvChan
}

func (db *_ChangeNoticeDao) RemoveRecv(watchId, recvId string) {
	defer recover()

	db.lock.Lock()
	defer db.lock.Unlock()

	recvIdList, ok := db.watchToRecvIdMap[watchId]
	if ok {
		newRecvIdList := []string{}
		for _, cmpRecvId := range recvIdList {
			if cmpRecvId != recvId {
				newRecvIdList = append(newRecvIdList, cmpRecvId)
			}
		}
		db.watchToRecvIdMap[watchId] = newRecvIdList
	}

	recvChan, ok := db.recvChanMap[recvId]
	if ok {
		close(recvChan)
		delete(db.recvChanMap, recvId)
	}
}

func (db *_ChangeNoticeDao) SendChange(watchId, changeId, callId string) error {
	//获取所有的chan
	recvChanList := db.getRecvChanList([]string{watchId})
	for _, recvChan := range recvChanList {
		db.sendChange(recvChan, changeId, callId)
	}
	return nil
}

func (db *_ChangeNoticeDao) sendChange(recvChan chan *ChangeAndCallId, changeId, callId string) {
	defer recover()

	select {
	case recvChan <- &ChangeAndCallId{
		ChangeId: changeId,
		CallId:   callId,
	}:
	default:
	}
}

func (db *_ChangeNoticeDao) getRecvChanList(watchIdList []string) []chan *ChangeAndCallId {
	db.lock.Lock()
	defer db.lock.Unlock()

	retList := []chan *ChangeAndCallId{}
	for _, watchId := range watchIdList {
		recvIdList, ok := db.watchToRecvIdMap[watchId]
		if !ok {
			continue
		}
		for _, recvId := range recvIdList {
			recvChan, ok := db.recvChanMap[recvId]
			if ok {
				retList = append(retList, recvChan)
			}
		}
	}
	return retList
}
